GroundTraffic kit for X-Plane®

Overview

This kit allows X-Plane scenery designers to add animated ground vehicle traffic to airport scenery packages. It requires X-Plane 10.0 or later.

How it works

This kit supplies a plugin that you can distribute with your scenery package. The plugin reads instructions from a text file that you create (and which you should also distribute with your scenery package) and animates X-Plane scenery objects according to those instructions. The objects to be animated can come from X-Plane's built-in library, from an add-on object library (e.g. OpenSceneryX), or from your scenery package.

Installation

Animation instructions

Use Notepad, TextEdit, or any other text editor to create a plain text file named GroundTraffic.txt in your scenery package folder. Save this blank file with an “ANSI”, “Western” or “UTF-8” encoding. (If using TextEdit, you may have to first choose Format → Make Plain Text to see those choices).

Add a “Header” statement to this file, followed by one or more “Routes”:

Header

The Header statement tells the plugin the location of your airport. It should be of the form “ICAO lat lon”, where:

ICAO
Four-character ICAO airport code.
lat & lon
A location near the centre of your airport. The control tower is often a good choice.

For example Seattle-Tacoma airport tower:

KSEA 	47.4557260 -122.3013928

Route

A Route statement starts a new animation. It should be of the form “route speed offset heading object”, where:

speed
The speed of the animated object, in km/h.
offset
Offset in metres to shift the object forwards before animation.
heading
Rotation in degrees to be applied to the object before animation.
object
The name of the animated object. This can be the name of a library object from X-Plane's built-in library or from an add-on library, the name of an object in your scenery package, or the name of a “Train”.

For the animation to look correct objects should be modelled such that they are pointing North and are roughly centered at their origin (since the plugin rotates them about their origin).

For example, a route using an object from the scenery package, travelling at 30km/h (~18mph):


route	30	0	0	objects/airport_fuel_truck.obj
...

A route using an object from X-Plane 10's built-in library, travelling at 24km/h (~15mph), to be rotated 180°:


route	24	0	180	lib/airport/Ramp_Equipment/Luggage_Truck.obj
...

A route using an object from the OpenSceneryX library, travelling at 20km/h (~12mph), shifted forwards 2.5m so that it rotates about its center:


route	20	2.5	0	opensceneryx/objects/airport/vehicles/loaders/6.obj
...

The Route statement should be preceded by a blank line and should be followed by a sequence of “waypoints” and “commands”. The Route ends with a blank line.

Waypoint

Animated objects move from one waypoint to the next at the speed specified in the Route statement. When the object passes the last waypoint it proceeds towards the first waypoint, forming a circular route (unless you specify a “reverse” command).

Waypoints should be of the form “lat lon”. For example:

...
47.4484450 -122.3001950
...

You can use OverlayEditor or WED to map out your route, typing the the waypoint locations into GroundTraffic.txt as you go. You may also want to consider placing a “line” (e.g. one of opensceneryx/lines/airport/zone_outlines/...) in OverlayEditor or WED to record your route; this will make it easier if you want to adjust your route in the future. But remember to remove or hide these lines before publishing your scenery package.

Objects will try to avoid crashing into each other by waiting at a waypoint if an object on another route is crossing ahead. So where routes cross don't leave a large distance between the waypoints on either side of the crossing point.

Pause command

The Pause command instructs the animated object to wait at the preceding waypoint for a while before moving on. Optionally, you can cause the value of a DataRef to change while the animated object is waiting, and change back before it proceeds.

The Pause command should be of the form “pause time set name slope curve duration”, where:

time
Time to wait, in seconds.
set name slope curve duration (optional)
As for the “Set” command.

For example, waiting at a waypoint for 30 minutes:

...
47.4629025 -122.3020905
pause 1800
...

Waiting at a waypoint for one minute while setting the value of the DataRef marginal/groundtraffic/var[0] such that it rises from 0 to 1 over five seconds, stays at 1, then starts going back to 0 five seconds before the object proceeds:

...
47.4380074 -122.3040742
pause 60 set var[0] rise linear 5
...

At command

The At command instructs the animated object to wait at the preceeding waypoint until a particular time of day. It should be of the form “at HH:MM on days”, where:

HH:MM
Times of day at which to proceed with the animation. Up to 24 times can be specified, in local time, and using a 24 hour clock.
days (optional)
Days on which to proceed with the animation. Specified in English.

For example, an animation that waits until 8am:

...
47.4559849 -122.3028592
at 08:00
...

An animation that waits until 8am or 8pm on a weekday:

...
47.4559849 -122.3028592
at 08:00 20:00 on Mon Tue Wed Thu Fri
...

When command

The When command instructs the animated object to wait at the preceeding waypoint until a DataRef is within a specified range. (This command is similar in concept to ANIM_show in .obj files). It should be of the form “when name from to”, where:

name
The name of a DataRef published by the sim or by another plugin. To access an array DataRef, append the array index within square brackets “[n]” to the name.
from to
Range of values for the DataRef for which the animation proceeds.

For example, an animation that only takes place in daylight:

...
47.4559849 -122.3028592
when sim/graphics/scenery/percent_lights_on 0 0.2
...

Backup command

The Backup command instructs the animated object to reverse from the preceding waypoint as far as the next waypoint, and thereafter move forward as normal. If the preceding waypoint also has a Pause command the object points forwards while waiting, and then backs-up after waiting.

The Backup command just consists of the word “backup”.

For example backing-up into a parking spot:

...
47.4348468 -122.3034628
backup
47.4349236 -122.3034600
pause 60
47.4348468 -122.3034628
...

Backing-up after a pause:

...
47.4379349 -122.3040074
47.4380074 -122.3040742
pause 60
backup
47.4379349 -122.3040074
...

For best results the waypoints before and after backing-up should be at the same location, as in the above examples, or at least in a straight line.

Reverse command

Normally, when the animated object passes the last waypoint it proceeds towards the first waypoint, forming a circular route. The Reverse command instead instructs the object to change direction at the last waypoint and re-trace its steps.

The Reverse command just consists of the word “reverse” and must be at the end of the Route. For example:

...
reverse

Note: You can't use the Reverse command in a route that contains Backup commands.

Set command

The Set command causes the value of a DataRef to change when the animated object arrives at the preceding waypoint. It should be of the form “set name slope curve duration”, where:

name
var[0] ... var[9] or the name of a custom DataRef.
slope
rise or fall - whether the value the DataRef rises from 0.0 to 1.0, or falls from 1.0 to 0.0.
curve
linear or sine - whether the value the DataRef changes linearly or like  ∫ over the duration.
duration
The time in seconds that the DataRef takes to change value. This can be 0 if you want the DataRef to change value instantly.

If you specify a name of the form var[n] then this command controls the “array” DataRef marginal/groundtraffic/var[n], which can be used to drive animations in a 3D modelling application that supports X-Plane animations. Each object will see values for this DataRef that are specific to the route that the object is following; so it is safe to re-use this DataRef across different objects and routes. For example, within one GroundTraffic.txt file, you could use marginal/groundtraffic/var[0] to control an animated belt in one or more beltloader objects, and also use marginal/groundtraffic/var[0] to control a refueling animation in one or more fuel truck objects. However, because the values returned for this DataRef are specific to a route, you can't usefully use it in a static object that is placed conventionally within an X-Plane scenery package.

Alternatively you can specify the name of a custom DataRef of your choice, but which should be unique to this scenery package. This DataRef can be used to animate objects that are used in a route and/or static objects that are placed conventionally within an X-Plane scenery package. Because all objects (either static or animated by this plugin) will see the same value for your custom DataRef it doesn't make sense to use the same custom DataRef in more than one route.

For example, setting the value of the DataRef marginal/groundtraffic/var[1] such that it rises from 0 to 1 over five seconds on hitting a waypoint:

...
47.4380074 -122.3040742
set var[1] rise linear 5
...

Setting the value of a custom DataRef such that it falls from 1 to 0 over two seconds on hitting a waypoint:

...
47.4348578 -122.3034624
set my/custom/dataref fall sine 2
...

The “Pause ... set” command also supports changing the value of a custom DataRef when the animated object arrives at a waypoint. The “Pause ... set” command restores the DataRef to its previous value before the object moves on from the waypoint; this command does not.

Comment

Lines starting with “#” are treated as comments and are ignored. For example:

# This is a comment

Debug

The Debug statement tells the plugin to plot out and number all waypoints. This is useful for checking that your waypoints are at the locations that you intended. The Debug statement just consists of the word “debug” and should be preceded by a blank line:

debug

Train

Instead of animating a single object along a Route, you can animate a number of objects to follow each other in succession like train cars/coaches follow their locomotive.

A Train statement starts a description of a train of connected objects. It should be of the form “train name”, where:

name
The name of your train. Use this name in a Route statement to animate this train. To avoid any ambiguity don't name your train with the same name as a library object or an object in your scenery package.

For example a suitable name for a train consisting of a tug and four luggage carts:


train	marginal/luggage_train_4
...

The Train statement should be preceded by a blank line and should be followed by a list of the “Car” statements. The Train description ends with a blank line.

Car

A train Car statement should be of the form “lag offset heading object”, where:

lag
Distance in metres that the object should lag behind the lead object in the train.
offset
Offset in metres to be applied to the object before animation.
heading
Rotation in degrees to be applied to the object before animation.
object
The name of the animated object. This can be the name of a library object from X-Plane's built-in library or from an add-on library, or the name of an object in your scenery package. It should not be the name of this or another Train.

To determine how far an object should lag behind the the lead object you can open/import the objects in your 3D modelling application and measure how far (in metres) you have to move the object behind the lead object for it to appear to “link up” correctly. If either object needs an offset to be centered on its axes then adjust for this before measuring. Repeat the process for further objects.

For example two objects, both of which need to be rotated 180°, the second of which is 3.36m behind the first:

...
0	0	180	lib/airport/Ramp_Equipment/Luggage_Truck.obj
3.36	0	180	lib/airport/Ramp_Equipment/Luggage_Cart.obj
...

The plugin animates train Car objects as if they are connected to each other so don't leave huge gaps between Cars. In particular, if you want to send two or more separate objects down the same route don't (ab)use the Train statement; just duplicate the route and change the order of the waypoints in the copy/copies to space out the objects.

Animation DataRefs

The plugin publishes the following DataRefs that you can use to create animated objects in a 3D modelling application that supports X-Plane animations:

marginal/groundtraffic/distance
Distance travelled from the first waypoint, in metres. Resets to zero every time the object passes the first waypoint. See below for how to use this to animate rotating wheels.

marginal/groundtraffic/speed
Speed of the object, in metres/second. This returns zero if the object is stationary for any reason, up to the speed that you specified in the Route statement (converted to [m/s]) if it is moving, or negative if it is backing-up (which is useful for displaying reversing lights).

marginal/groundtraffic/var[0] ... var[9]
DataRef whose value is controlled by the “Set” and “Pause ... set” commands.

marginal/groundtraffic/waypoint/last
The last waypoint in the Route (counting from zero) visited by the object.

marginal/groundtraffic/waypoint/last/distance
The distance from the last waypoint, in metres. This returns zero if the object is stationary.

marginal/groundtraffic/waypoint/next
The next waypoint in the Route (counting from zero) visited by the object. This is one greater than the last waypoint unless the object is reversing its route or is circling back to the first waypoint.

marginal/groundtraffic/waypoint/next/distance
The distance to the next waypoint, in metres.

These DataRefs return values specific to the route that the object is following; so they are only useful in animating objects on routes controlled by this plugin, not in static objects that are placed conventionally within an X-Plane scenery package. (You can use the “Set” and/or “Pause ... set” commands with a custom DataRef name to publish DataRefs for use in static objects). You can examine the values of these DataRefs using DataRefEditor, but it will only display the values for the first route listed in GroundTraffic.txt.

Animating rotating wheels

The speed of rotation of a wheel depends on its size; a smaller wheel needs to rotate more quickly to cover a given distance than a larger wheel. So in your 3D modelling application measure the diameter of the wheel (in metres) and multiple this value by π to obtain the wheel's circumference.

Set up an animation for the wheel containing two keyframes. Rotate the wheel 90° forwards around its axle between the two keyframes. Specify the X-Plane animation values as follows:

For example, for a wheel 1.155m in diameter:

Troubleshooting

You can check that the plugin has been loaded and is operating correctly by opening the file Log.txt in the X-Plane folder. You should see:

Fetching plugins for Custom Scenery/my scenery package/plugins
Loaded: Custom Scenery/my scenery package/plugins/GroundTraffic/mac.xpl.

If the plugin is operating correctly it produces no other output in the log. However if the plugin has a problem reading your GroundTraffic.txt file you will see one or more entries starting with “GroundTraffic:” in the log and the plugin will not perform any animation. For example:

GroundTraffic: Empty route at line 15

The plugin examines your GroundTraffic.txt file when you make a selection from the Location → Select Global Airport dialog; if you have edited the file then the plugin will re-read it and re-start the animations. Or you can force the plugin to re-read the file, re-load the objects, and re-start the animations by disabling and re-enabling it in the Plugin → Plugin Admin → Enable/Disable dialog.

Acknowledgements

“X-Plane” is a registered trademark of Laminar Research.

License

This kit is licensed under the Creative Commons Attribution license. In short, you can use the plugin provided by this kit in commerical scenery packages, but you must give the author credit.

The author would appreciate a courtesy copy of any commercial scenery that you make using this kit, but you are under no obligation.